#pragma once
#include "wlroots.hpp"
#include "utils.h"
#include "macros.h"
#include "server.h"

extern "C" {
#include <wlr/types/wlr_cursor.h>
}

#include <sigc++/sigc++.h>

#include <list>
#include <array>

class CursorWrapper
{
public:
    CursorWrapper(Server* server);
    ~CursorWrapper();

    inline struct wlr_cursor* cursor() { return m_cursor; }
    void set_cursor_default();

    inline void set_cursor_mode(cursor_mode mode) { m_cursor_mode = mode; }
    inline double x() { return m_cursor->x; }
    inline double y() { return m_cursor->y; }
    inline double grab_x() { return m_grab_x; }
    inline double grab_y() { return m_grab_y; }
    inline void set_grab_x(double x) { m_grab_x = x; }
    inline void set_grab_y(double y) { m_grab_y = y; }
    inline void set_grab_geobox(struct wlr_box b) { m_grab_geobox = b; }
    inline struct wlr_box grab_geobox() { return m_grab_geobox; }
    inline void inc_grab_geobox_x(int x) { m_grab_geobox.x += x; }
    inline void inc_grab_geobox_y(int y) { m_grab_geobox.y += y; }
    inline wlr_edges resize_edges() { return m_resize_edges; }
    inline void set_resize_edges(wlr_edges e) { m_resize_edges = e; }

    sigc::signal<void(double, double, uint32_t)> sig_cursor_motion; //x y time
    sigc::signal<void(double, double, wlr_pointer_button_event*)> sig_cursor_button; //x y event
    sigc::signal<void(wlr_pointer_axis_event*)> sig_cursor_axis; //event
    sigc::signal<void()> sig_cursor_frame;
    sigc::signal<void(int, int)> sig_cursor_move; //x y
    // sigc::signal<void(int, int, int, int, uint32_t)> sig_cursor_resize; //left, right, top, bottom, time
    sigc::signal<void(uint32_t)> sig_cursor_resize; //time


private:
    void cursor_motion(wlr_pointer_motion_event *event);
    void cursor_motion_absolute(wlr_pointer_motion_absolute_event* event);
    void cursor_button(wlr_pointer_button_event* event);
    void cursor_axis(wlr_pointer_axis_event* event);
    void cursor_frame();

    void process_cursor_motion(uint32_t time);
    void process_cursor_move(uint32_t time);
    void process_cursor_resize(uint32_t time);

private:
    Server *m_server;

    struct wlr_cursor *m_cursor;
    struct wlr_xcursor_manager *m_cursor_mgr;
    wl_listener_wrapper m_cursor_motion;
    wl_listener_wrapper m_cursor_motion_absolute;
    wl_listener_wrapper m_cursor_button;
    wl_listener_wrapper m_cursor_axis;
    wl_listener_wrapper m_cursor_frame;

    enum cursor_mode m_cursor_mode;

    double m_grab_x;
    double m_grab_y;
    struct wlr_box m_grab_geobox;
    wlr_edges m_resize_edges;
};
